<template>
  <div class="code-preview">
    <div class="header">
      <div class="left">
        <h3>生成的代码</h3>
        <el-select v-model="language" size="small" style="margin-left: 10px;">
          <el-option label="Java" value="java" />
          <el-option label="C" value="c" />
          <el-option label="C++" value="cpp" />
        </el-select>
      </div>
      <div class="actions">
        <el-button-group>
          <el-button type="primary" @click="generateCode" :loading="generating">
            生成代码
          </el-button>
          <el-button type="success" @click="downloadCode" :disabled="!code">
            下载代码
          </el-button>
          <el-button @click="copyCode" :disabled="!code">
            复制代码
          </el-button>
        </el-button-group>
      </div>
    </div>
    
    <div class="code-container">
      <div class="custom-tabs" key="tabs-container">
        <div class="tabs-header">
          <div 
            class="tab-item" 
            :class="{ 'active': activeTab === 'preview' }"
            @click="switchTab('preview')"
          >
            代码预览
          </div>
          <div 
            class="tab-item" 
            :class="{ 'active': activeTab === 'result' }"
            @click="switchTab('result')"
          >
            运行结果
          </div>
        </div>
        <div class="tabs-content">
          <div v-show="activeTab === 'preview'" class="tab-pane">
            <pre><code :class="['language-' + language]" ref="codeBlock">{{ code }}</code></pre>
          </div>
          <div v-show="activeTab === 'result'" class="tab-pane">
            <div class="result-container">
              <pre>{{ runResult }}</pre>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch, computed, nextTick } from 'vue'
import { useComponentStore } from '../stores/component'
import Prism from 'prismjs'
import 'prismjs/themes/prism.css'
import 'prismjs/components/prism-java'
import 'prismjs/components/prism-c'
import 'prismjs/components/prism-cpp'
import { ElMessage, ElMessageBox } from 'element-plus'

const props = defineProps({
  nodes: {
    type: Array,
    required: true
  },
  connections: {
    type: Array,
    required: true
  }
})

const componentStore = useComponentStore()
const language = ref('java')
const code = ref('')
const generating = ref(false)
const activeTab = ref('preview')
const runResult = ref('')
const codeBlock = ref(null)

// 监听节点和连接的变化
watch(() => props.nodes, () => {
  resetCode()
}, { deep: true })

watch(() => props.connections, () => {
  resetCode()
}, { deep: true })

// 重置代码和结果
const resetCode = () => {
  code.value = ''
  runResult.value = ''
  activeTab.value = 'preview'
}

// 检查数据结构和算法是否正确连接
const validateConnections = computed(() => {
  const dataStructures = ['adjacencyMatrix', 'adjacencyList', 'array', 'binaryTree', 'heap']
  const algorithms = ['dijkstra', 'bubbleSort', 'bfs', 'quickSort', 'dfs', 'mergeSort', 'prim', 'kruskal', 'binarySearch']
  
  // 检查是否有数据结构节点
  const hasDataStructure = props.nodes.some(node => dataStructures.includes(node.type))
  // 检查是否有算法节点
  const hasAlgorithm = props.nodes.some(node => algorithms.includes(node.type))
  
  if (!hasDataStructure || !hasAlgorithm) {
    return '请添加数据结构和算法节点'
  }
  
  // 检查是否有连接
  if (props.connections.length === 0) {
    return '请将数据结构与算法连接'
  }
  
  // 验证每个连接是否合法
  for (const conn of props.connections) {
    const sourceNode = props.nodes.find(n => n.id === conn.source)
    const targetNode = props.nodes.find(n => n.id === conn.target)
    
    if (!sourceNode || !targetNode) continue
    
    if (!componentStore.validateConnection(sourceNode.type, targetNode.type)) {
      return `${sourceNode.data.name} 不能连接到 ${targetNode.data.type}`
    }
  }
  
  return null // 验证通过
})

const generateCode = async () => {
  // 先验证连接
  const validationError = validateConnections.value
  if (validationError) {
    ElMessage.warning(validationError)
    return
  }

  // 显示加载中提示
  const msgboxId = 'code-generation-msgbox-' + Date.now();
  const msgboxDiv = document.createElement('div');
  msgboxDiv.className = 'el-message-box__wrapper';
  msgboxDiv.id = msgboxId;
  msgboxDiv.style.position = 'fixed';
  msgboxDiv.style.top = '0';
  msgboxDiv.style.right = '0';
  msgboxDiv.style.bottom = '0';
  msgboxDiv.style.left = '0';
  msgboxDiv.style.display = 'flex';
  msgboxDiv.style.justifyContent = 'center';
  msgboxDiv.style.alignItems = 'center';
  msgboxDiv.style.zIndex = '2001';
  msgboxDiv.innerHTML = `
    <div class="el-message-box" style="width: 420px; max-width: 90%;">
      <div class="el-message-box__header">
        <div class="el-message-box__title">代码生成中</div>
      </div>
      <div class="el-message-box__content">
        <div class="el-message-box__container">
          <div class="el-message-box__message">
            <p>正在通过 AI 生成代码，请稍候...</p>
            <div style="display: flex; justify-content: center; margin-top: 20px;">
              <div class="el-loading-spinner">
                <svg class="circular" viewBox="25 25 50 50">
                  <circle class="path" cx="50" cy="50" r="20" fill="none"></circle>
                </svg>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  `;
  document.body.appendChild(msgboxDiv);
  
  // 添加背景遮罩
  const modalDiv = document.createElement('div');
  modalDiv.className = 'v-modal';
  modalDiv.style.position = 'fixed';
  modalDiv.style.top = '0';
  modalDiv.style.right = '0';
  modalDiv.style.bottom = '0';
  modalDiv.style.left = '0';
  modalDiv.style.opacity = '0.5';
  modalDiv.style.backgroundColor = '#000';
  modalDiv.style.zIndex = '1999';
  document.body.appendChild(modalDiv);
  
  // 函数用于关闭弹窗
  const closeMessageBox = () => {
    document.getElementById(msgboxId)?.remove();
    document.querySelector('.v-modal')?.remove();
  };

  generating.value = true
  try {
    const generatedCode = await componentStore.generateCode(props.nodes, props.connections, language.value)
    if (generatedCode) {
      // 分离代码和运行结果
      if (generatedCode.code && generatedCode.result) {
        code.value = generatedCode.code
        runResult.value = generatedCode.result
      } else {
        code.value = generatedCode
        runResult.value = '运行成功，无明显输出结果。'
      }
      // 关闭弹窗
      closeMessageBox();
      ElMessage.success('代码生成成功')
      // 切换到代码预览标签
      activeTab.value = 'preview'
    }
  } catch (error) {
    // 关闭弹窗
    closeMessageBox();
    console.error('代码生成失败:', error);
    ElMessage.error('代码生成失败')
  } finally {
    generating.value = false
    // 确保弹窗关闭
    setTimeout(closeMessageBox, 100);
  }
}

const downloadCode = () => {
  if (!code.value) return
  
  const extensions = {
    java: 'java',
    c: 'c',
    cpp: 'cpp'
  }
  
  const filename = `generated-code.${extensions[language.value]}`
  const blob = new Blob([code.value], { type: 'text/plain' })
  const url = window.URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  window.URL.revokeObjectURL(url)
  
  ElMessage.success('代码下载成功')
}

const copyCode = async () => {
  if (!code.value) return
  
  try {
    await navigator.clipboard.writeText(code.value)
    ElMessage.success('代码已复制到剪贴板')
  } catch (err) {
    ElMessage.error('复制失败')
  }
}

// 添加切换标签页的方法
const switchTab = (tab) => {
  console.log('切换到标签页:', tab)
  activeTab.value = tab
  // 强制重新渲染
  nextTick(() => {
    if (tab === 'preview' && codeBlock.value) {
      Prism.highlightElement(codeBlock.value)
    }
  })
}

watch(() => code.value, () => {
  nextTick(() => {
    if (codeBlock.value) {
      Prism.highlightElement(codeBlock.value)
    }
  })
})

onMounted(() => {
  if (codeBlock.value) {
    Prism.highlightElement(codeBlock.value)
  }
})
</script>

<style scoped>
.code-preview {
  height: 100%;
  padding: 16px;
  background: #f5f7fa;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.left {
  display: flex;
  align-items: center;
  gap: 10px;
  
  h3 {
    margin: 0;
  }
}

.actions {
  display: flex;
  gap: 10px;
}

.code-container {
  height: calc(100% - 60px);
  overflow: auto;
  background: white;
  border-radius: 4px;
  padding: 16px;
}

pre {
  margin: 0;
  padding: 16px;
  background: #f8f8f8;
  border-radius: 4px;
  overflow-x: auto;
  font-family: 'JetBrains Mono', 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.6;
  white-space: pre !important;
  tab-size: 4;
  max-height: none !important;
}

code {
  display: block;
  font-family: 'JetBrains Mono', 'Courier New', Courier, monospace;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
  background: transparent;
  white-space: pre !important;
  word-break: normal !important;
  word-wrap: normal !important;
  overflow-wrap: normal !important;
}

.result-container {
  padding: 16px;
  background: #1e1e1e;
  color: #fff;
  border-radius: 4px;
  font-family: 'JetBrains Mono', 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.6;
  white-space: pre !important;
  overflow-x: auto;
}

.result-container pre {
  margin: 0;
  padding: 0;
  background: transparent;
  color: #fff;
  font-family: inherit;
}

/* 命令行样式 */
.result-container pre {
  position: relative;
}

.result-container pre :deep(*) {
  font-family: 'JetBrains Mono', 'Courier New', Courier, monospace !important;
}

/* 命令提示符样式 */
.result-container pre :deep(span:first-child) {
  color: #4EC9B0;
}

/* 输出内容样式 */
.result-container pre :deep(span.output) {
  color: #569CD6;
}

/* 错误信息样式 */
.result-container pre :deep(span.error) {
  color: #F44747;
}

/* 成功信息样式 */
.result-container pre :deep(span.success) {
  color: #6A9955;
}

/* 添加闪烁的光标效果 */
.result-container pre::after {
  content: '';
  position: absolute;
  bottom: 0;
  width: 8px;
  height: 15px;
  background: #fff;
  animation: blink 1s step-end infinite;
  display: none; /* 默认不显示 */
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* 当容器获得焦点时显示光标 */
.result-container:hover pre::after {
  display: block;
}

.custom-tabs {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.tabs-header {
  display: flex;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}

.tab-item {
  padding: 10px 20px;
  cursor: pointer;
  border-radius: 4px 4px 0 0;
  border: 1px solid transparent;
  border-bottom: none;
  font-size: 14px;
  color: #303133;
  transition: all 0.3s;
  user-select: none;
  position: relative;
  z-index: 1;
}

.tab-item:hover {
  color: #409eff;
}

.tab-item.active {
  color: #409eff;
  background-color: white;
  border-color: #e4e7ed;
  border-bottom-color: white;
  margin-bottom: -1px;
  font-weight: bold;
}

.tabs-content {
  flex: 1;
  padding: 16px;
  background-color: white;
  overflow: auto;
  position: relative;
  z-index: 0;
}

.tab-pane {
  height: 100%;
  overflow: auto;
}

/* 代码高亮样式 */
:deep(.token.comment),
:deep(.token.prolog),
:deep(.token.doctype),
:deep(.token.cdata) {
  color: #6a9955;
}

:deep(.token.punctuation) {
  color: #808080;
}

:deep(.token.property),
:deep(.token.tag),
:deep(.token.boolean),
:deep(.token.number),
:deep(.token.constant),
:deep(.token.symbol),
:deep(.token.deleted) {
  color: #b5cea8;
}

:deep(.token.selector),
:deep(.token.attr-name),
:deep(.token.string),
:deep(.token.char),
:deep(.token.builtin),
:deep(.token.inserted) {
  color: #ce9178;
}

:deep(.token.operator),
:deep(.token.entity),
:deep(.token.url),
:deep(.language-css .token.string),
:deep(.style .token.string) {
  color: #d4d4d4;
}

:deep(.token.atrule),
:deep(.token.attr-value),
:deep(.token.keyword) {
  color: #569cd6;
}

:deep(.token.function),
:deep(.token.class-name) {
  color: #dcdcaa;
}

:deep(.token.regex),
:deep(.token.important),
:deep(.token.variable) {
  color: #d16969;
}
</style> 